package com.test;

import java.io.*;
import java.nio.file.*;
import java.nio.file.attribute.BasicFileAttributes;
import java.util.*;

import com.alibaba.fastjson2.JSON;
import com.alibaba.fastjson2.JSONArray;
import com.alibaba.fastjson2.JSONObject;
import com.alibaba.fastjson2.TypeReference;
import org.apache.hc.client5.http.auth.AuthScope;
import org.apache.hc.client5.http.auth.UsernamePasswordCredentials;
import org.apache.hc.client5.http.classic.methods.HttpPost;
import org.apache.hc.client5.http.impl.auth.BasicCredentialsProvider;
import org.apache.hc.client5.http.impl.classic.CloseableHttpClient;
import org.apache.hc.client5.http.impl.classic.CloseableHttpResponse;
import org.apache.hc.client5.http.impl.classic.HttpClients;
import org.apache.hc.core5.http.ContentType;
import org.apache.hc.core5.http.ParseException;
import org.apache.hc.core5.http.io.entity.EntityUtils;
import org.apache.hc.core5.http.io.entity.StringEntity;
import org.apache.poi.hssf.usermodel.HSSFWorkbook;
import org.apache.poi.ss.usermodel.*;
import org.apache.poi.xssf.streaming.SXSSFWorkbook;
import org.apache.poi.xssf.usermodel.XSSFWorkbook;

import java.util.stream.Collectors;

/**
 * Hello world!
 *
 */
public class App 
{
    static class ItemData{
        private String name;
        private String type;

        public String getName() {
            return name;
        }

        public void setName(String name) {
            this.name = name;
        }

        public String getType() {
            return type;
        }

        public void setType(String type) {
            this.type = type;
        }

        public Long getValue() {
            return value;
        }

        public void setValue(Long value) {
            this.value = value;
        }

        private Long value;
    }

    public static void main(String[] args) {
        Scanner scanner = new Scanner(System.in); // 创建 Scanner 对象
        System.out.print("请输入数据文件（示例： D:\\dep.txt）: ");    // 提示用户输入
        String templatePath = scanner.nextLine();         // 接收整行输入
        try(BufferedReader reader = new BufferedReader(new FileReader(templatePath));){
            // 读取txt文件内容
            StringBuilder content = new StringBuilder();
            String line = reader.readLine();
            while (line != null) {
                content.append(line);
                line = reader.readLine();
            }
            // 转成对象
            //Map<String, String> data = JSON.parseObject(content.toString(), new TypeReference<Map<String, String>>() {});
            List<App.ItemData> data = JSON.parseObject(content.toString(), new TypeReference<List<App.ItemData>>() {});
            //for(Map.Entry<String, String> it : data.entrySet()){
            for(App.ItemData it : data){

            }

        } catch (IOException e) {
            throw new RuntimeException(e);
        }


    }

    // 参考示例 https://www.cnblogs.com/niumoo/p/16611965.html
    public static String post(String url, String jsonBody) {

        final BasicCredentialsProvider credsProvider = new BasicCredentialsProvider();
        credsProvider.setCredentials(
                new AuthScope("httpbin.org", 80),
                new UsernamePasswordCredentials("admin", "123456".toCharArray()));

        //final HttpGet httpget = new HttpGet("http://httpbin.org/basic-auth/admin/123456");
        String result = null;
        final HttpPost httpPost = new HttpPost(url);
        httpPost.setEntity(new StringEntity(jsonBody, ContentType.APPLICATION_JSON));

        try (CloseableHttpClient httpclient = HttpClients.custom().setDefaultCredentialsProvider(credsProvider).build();
             CloseableHttpResponse response = httpclient.execute(httpPost)) {
            // 获取响应信息
            result = EntityUtils.toString(response.getEntity());
        } catch (IOException | ParseException e) {
            e.printStackTrace();
        }
        return result;
    }

    public static void main1( String[] args )
    {
        Scanner scanner = new Scanner(System.in); // 创建 Scanner 对象
        System.out.print("请输入模板文件的全路径: ");    // 提示用户输入
        String templatePath = scanner.nextLine();         // 接收整行输入
        System.out.println("您模板文件的全路径= , " + templatePath + "!");
        File file = new File(templatePath);
        if (!file.exists()) {
            System.out.println("模板文件不存在: " + templatePath);
            return;
        }
        List<String> templateData = readXlsx(file.toPath());
        assert templateData != null;
        int headSize = templateData.size();
        String templateStr = String.join(",", templateData);
        /*String templateStr = "";
        StringBuilder templateStrSb = new StringBuilder();
        for(String item : templateData){
            // // 使用正则表达式去除前后的空格（包括全角和半角空格）
            templateStrSb.append(item.replaceAll("^[\\s\u3000]+|[\\s\u3000]+$", ""));
        }
        templateStr = templateStrSb.toString();*/

        //System.out.println("模板第一行头信息："+templateStr);


        System.out.print("请输入要搜索的目录路径: ");    // 提示用户输入
        String startDir = scanner.nextLine(); // 替换为实际的目录路径
        System.out.println("您输入的搜索的目录路径= , " + startDir );
        // 检查路径是否存在并且是目录
        File directory = new File(startDir);
        if (!directory.exists()) {
            System.out.println("目录不存在: " + startDir);
            return;
        }

        if (!directory.isDirectory()) {
            System.out.println("不是目录: " + startDir);
            return;
        }

        scanner.close(); // 关闭 Scanner 对象
        // 指定要搜索的目录
        // String startDir = "path_to_directory"; // 替换为实际的目录路径
        List<Path> xlsxFiles = new ArrayList<>();

        try {
            Files.walkFileTree( Paths.get(startDir), new SimpleFileVisitor<Path>() {
                @Override
                public FileVisitResult visitFile(Path file, BasicFileAttributes attrs) throws IOException {
                    // 检查文件扩展名
                    String fileName = file.getFileName().toString().toLowerCase();
                    if (fileName.endsWith(".xls") || fileName.endsWith(".xlsx")) {
                        //System.out.println("Found Excel file: " + file.toAbsolutePath());
                        xlsxFiles.add(Paths.get(file.toAbsolutePath().toUri()));
                    }
                    return FileVisitResult.CONTINUE; // 继续遍历
                }

                @Override
                public FileVisitResult visitFileFailed(Path file, IOException exc) throws IOException {
                    // 当文件无法访问时打印错误信息
                    System.err.println("Error accessing file: " + file + " - " + exc.getMessage());
                    return FileVisitResult.CONTINUE; // 继续遍历
                }
            });
        } catch (IOException e) {
            System.err.println("Error traversing directory: " + e.getMessage());
        }

        List<String> xiangtong = new ArrayList<>();
        List<String> butong = new ArrayList<>();
        List<String> emptyFiles = new ArrayList<>();
        // 输出所有找到的 .xlsx 文件
        //System.out.println("Found .xlsx files:");
        // xlsxFiles.forEach(System.out::println);
        System.out.println("头信息部不相等的文件列表");
        for(Path path : xlsxFiles){
            System.out.println(path.toString());
            try{
                String templateStrItem = String.join(",", Objects.requireNonNull(readXlsx(path)));
                //System.out.println("模板第一行头信息："+templateStrItem);
                //System.out.println(path.toFile().getAbsolutePath()+"头信息 : "+templateStrItem);
                if(templateStrItem.equals(templateStr)){
                    xiangtong.add(path.toString());
                }else{
                    butong.add(path.toString());
                }
            }catch (Exception e){
                //System.out.println(path + "加载出错");
                emptyFiles.add(path.toString());
                /*if(e.getMessage().contains("empty")){
                    emptyFiles.add(path.toString());
                }*/
            }
        }

        System.out.println("\n\n 匹配相同的文件列表");
        if(xiangtong.size() > 0){
            for(String item: xiangtong){
                System.out.println(item);
                // 获取数据
                List<String[]> data = readData(item, headSize);
                if(data.size()>0){
                    appendWrite(templatePath,data);
                }

            }
        }else {
            System.out.println("暂无数据");
        }

        System.out.println("\n\n 不匹配相同的文件列表");
        if(butong.size() > 0){
            for(String item: butong){
                System.out.println(item);
            }
        }else {
            System.out.println("暂无数据");
        }

        System.out.println("\n\n 异常文件列表");
        if(emptyFiles.size() > 0){
            for(String item: emptyFiles){
                System.out.println(item);
            }
        }else {
            System.out.println("暂无数据");
        }


    }


    public static List<String[]> readData(String filePath, int size) {
        // String filePath = "path_to_your_file.xlsx";  // Excel 文件路径
        List<String[]> data = new ArrayList<>();
        try (FileInputStream fis = new FileInputStream(new File(filePath))) {

            Workbook workbook;
            if (filePath.endsWith(".xlsx")) {
                workbook = new XSSFWorkbook(fis);  // 处理 .xlsx 文件
            } else if (filePath.endsWith(".xls")) {
                workbook = new HSSFWorkbook(fis);  // 处理 .xls 文件
            } else {
                throw new IllegalArgumentException("文件格式不支持");
            }

            // 获取第一个工作表
            Sheet sheet = workbook.getSheetAt(0);

            // 从第二行开始（跳过第一行）
            for (int i = 1; i <= sheet.getLastRowNum(); i++) {
                Row row = sheet.getRow(i);
                String[] itemData = new String[size];
                // 迭代列
                if (row != null) {
                    for (int j = 0; j < row.getLastCellNum(); j++) {
                        Cell cell = row.getCell(j);
                        if (cell != null) {
                            //System.out.print(cell.toString() + "\t");
                            itemData[j] = cell.toString();
                        }
                    }
                    //System.out.println();
                    data.add(itemData);
                }
            }

        } catch (IOException e) {
            e.printStackTrace();
        }

        return data;
    }

    public static List<String> readXlsx(Path path) {
        //String filePath = "path_to_file.xlsx"; // 替换为实际文件路径

        Workbook workbook = null;
        List<String> data = new ArrayList<>();
        try (FileInputStream fis = new FileInputStream(path.toFile());

             //Workbook workbook = WorkbookFactory.create(fis)
        ) {

            // Check file extension and use appropriate workbook type
            if (path.toString().endsWith(".xls")) {
                workbook = new HSSFWorkbook(fis); // For .xls files
            } else if (path.toString().endsWith(".xlsx")) {
                workbook = new XSSFWorkbook(fis); // For .xlsx files
            } else {
                throw new IllegalArgumentException("The provided file is not an Excel file.");
            }

            // 获取第一个工作表
            Sheet sheet = workbook.getSheetAt(0);

            // 获取第一行
            Row firstRow = sheet.getRow(0);
            if (firstRow != null) {

                String input = "　 Hello World!　 "; // 输入字符串，包含全角空格和半角空格
                // 使用正则表达式去除前后的空格（包括全角和半角空格）
                /*
                ^[\\s\u3000]+: 匹配字符串开头的半角空格 (\s) 和全角空格 (\u3000)。
                [\\s\u3000]+$: 匹配字符串结尾的半角空格和全角空格。*/
                String output = input.replaceAll("^[\\s\u3000]+|[\\s\u3000]+$", "");

                // 手动去除
                // 去除前后的半角空格
                String trimmed = input.replaceAll("^[\\s]+", "").replaceAll("[\\s]+$", "");
                // 去除前后的全角空格
                trimmed = trimmed.replaceAll("^[\\u3000]+", "").replaceAll("[\\u3000]+$", "");

                // 结合 trim去前后空格
                // 先去除全角空格
                String trimmed1 = input.replaceAll("^[\\u3000]+", "").replaceAll("[\\u3000]+$", "");
                // 然后使用 trim 去掉半角空格
                trimmed1 = trimmed1.trim();


                for (Cell cell : firstRow) {
                    // 根据单元格类型读取值
                    switch (cell.getCellType()) {
                        case STRING:
                            //System.out.print(cell.getStringCellValue() + "\t");
                            data.add(cell.getStringCellValue().replaceAll("^[\\s\u3000]+|[\\s\u3000]+$", ""));
                            break;
                        case NUMERIC:
                            if (DateUtil.isCellDateFormatted(cell)) {
                                //System.out.print(cell.getDateCellValue() + "\t");
                                data.add(cell.getDateCellValue().toString().replaceAll("^[\\s\u3000]+|[\\s\u3000]+$", ""));
                            } else {
                                //System.out.print(cell.getNumericCellValue() + "\t");
                                data.add((cell.getNumericCellValue()+"").replaceAll("^[\\s\u3000]+|[\\s\u3000]+$", ""));
                            }
                            break;
                        case BOOLEAN:
                            //System.out.print(cell.getBooleanCellValue() + "\t");
                            data.add((cell.getBooleanCellValue()+"").replaceAll("^[\\s\u3000]+|[\\s\u3000]+$", ""));
                            break;
                        case FORMULA:
                            //System.out.print(cell.getCellFormula() + "\t");
                            data.add(cell.getCellFormula().replaceAll("^[\\s\u3000]+|[\\s\u3000]+$", ""));
                            break;
                        case BLANK:
                            //System.out.print("BLANK\t");\
                            data.add("");
                            break;
                        default:
                            //System.out.print("UNKNOWN\t");
                            data.add("");
                            break;
                    }
                }

                //System.out.println(); // 换行
                return data;
            } else {
                System.out.println("The first row is empty.");
            }

        } catch (Exception e) {
            System.err.println("Error reading the Excel file: " + e.getMessage());
            //throw e;
        }finally {
            try {
                assert workbook != null;
                workbook.close();
            } catch (IOException e) {
                throw new RuntimeException(e);
            }
        }
        return null;
    }


    public static void write() {
        String filePath = "large_output.xlsx"; // 输出文件路径

        try (SXSSFWorkbook workbook = new SXSSFWorkbook(100); // 保持100行在内存中
             FileOutputStream fileOut = new FileOutputStream(new File(filePath))) {

            // 创建工作表
            Sheet sheet = workbook.createSheet("Sheet1");

            // 创建标题行
            Row headerRow = sheet.createRow(0);
            Cell headerCell1 = headerRow.createCell(0);
            headerCell1.setCellValue("ID");
            Cell headerCell2 = headerRow.createCell(1);
            headerCell2.setCellValue("Name");

            // 写入数据
            for (int i = 1; i <= 100000; i++) { // 假设我们要写入10万条数据
                Row row = sheet.createRow(i);
                row.createCell(0).setCellValue(i);
                row.createCell(1).setCellValue("Name" + i);
            }

            // 写入文件
            workbook.write(fileOut);
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    public static void appendWrite(String filePath, List<String[]> data) {
        //String filePath = "existing_file.xlsx";  // 已存在的xlsx文件
        //String[] newData = {"ID", "Name"};      // 新数据

        //FileOutputStream fileOut = null;
        try (FileInputStream fis = new FileInputStream(new File(filePath));
             XSSFWorkbook workbook = new XSSFWorkbook(fis);
             FileOutputStream fileOut = new FileOutputStream(new File(filePath))
                //Workbook workbook = WorkbookFactory.create(new FileInputStream(filePath));
                //FileOutputStream fileOut = new FileOutputStream(filePath)
        ) {

            // 获取现有的工作表
            Sheet sheet = workbook.getSheetAt(0); // 获取第一个工作表

            // 计算现有数据的行数
            //int lastRowNum = sheet.getLastRowNum();
            // 获取实际数据的行数，避免空行影响
            int lastRowNum = sheet.getPhysicalNumberOfRows(); // 计算实际有数据的行数

            // 如果没有数据，则从第一行开始插入
            if (lastRowNum == 0) {
                lastRowNum = 1;
            }

            // 在现有数据的末尾追加新的行
            /*Row newRow = sheet.createRow(lastRowNum + 1);
            for (int i = 0; i < newData.length; i++) {
                Cell newCell = newRow.createCell(i);
                newCell.setCellValue(newData[i]);
            }*/
            for (int i = 0; i < data.size(); i++) {
                Row newRow = sheet.createRow(lastRowNum + (i+1));
                String[] item = data.get(i);
                for (int j = 0; j < item.length; j++) {
                    Cell newCell = newRow.createCell(j);
                    newCell.setCellValue(item[j]);
                }
            }

            // 写回文件
            // 确保文件流正确
            //fileOut = new FileOutputStream(new File(filePath));
            workbook.write(fileOut);
            //System.out.println("数据已追加到文件中");
        } catch (IOException e) {
            e.printStackTrace();
        }
        /*finally {
            // 确保 FileOutputStream 正确关闭
            if (fileOut != null) {
                try {
                    fileOut.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }*/
    }

    public static void liushiWrite(String[] args) {
        String existingFilePath = "existing_file.xlsx";  // 已存在的xlsx文件
        String newFilePath = "new_file.xlsx";            // 新文件路径

        try (FileInputStream fis = new FileInputStream(new File(existingFilePath));
             XSSFWorkbook existingWorkbook = new XSSFWorkbook(fis);
             FileOutputStream fileOut = new FileOutputStream(new File(newFilePath))) {

            // 创建SXSSFWorkbook用于流式写入
            SXSSFWorkbook workbook = new SXSSFWorkbook(existingWorkbook, 100); // 保持100行在内存中

            // 获取现有工作表
            Sheet sheet = workbook.getSheetAt(0);  // 获取第一个工作表

            // 添加新的数据行
            for (int i = 0; i < 1000; i++) { // 假设我们要追加1000行
                Row row = sheet.createRow(sheet.getLastRowNum() + 1);
                row.createCell(0).setCellValue(i);
                row.createCell(1).setCellValue("Name" + i);
            }

            // 写入新文件
            workbook.write(fileOut);
            System.out.println("数据已流式写入新文件中");

        } catch (IOException e) {
            e.printStackTrace();
        }
    }

}
